/* --- Copyright University of Sussex 1992. All rights reserved. ----------
 * File:            $popvision/lib/straight_hough.c
 * Purpose:         Straight line finding by Hough Transform
 * Author:          David Young, Nov 12 1992 (see revisions)
 * Documentation:   HELP *STRAIGHT_HOUGH
 * Related Files:   LIB *STRAIGHT_HOUGH
 */

/* 
 *  Poplog code without an explicit copyright is covered by the
 *  following copy-right:  
 * 
 * Copyright (C) 1981-1999 The University of Sussex. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:  
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software. 
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE UNIVERSITY OF SUSSEX BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 *
 * Copyright notices in the Poplog code and documentation files do not
 * restrict use of those files in accord with this notice, as the
 * notices remain solely on account of requirements of the
 * installation software used by the original development team. 
 *
 * This Poplog distribution is based at the University of Birmingham
 * solely as a service to users. 
 * 
 * THE UNIVERSITY OF BIRMINGHAM GIVES NO WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE UNIVERSITY OF BIRMINGHAM OR
 * ANY OF THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
 */

/*
 * grabbed from: http://www.cs.bham.ac.uk/research/projects/poplog/popvision/lib/straight_hough.c
 */

#include <boost/python.hpp>
#include <math.h>

using namespace boost::python;

BOOST_PYTHON_MODULE(hough)
{
  def("hough", straight_hough_array_f);
}

/*  Notes:
 *  Ugh.  so much pointer math.  *hough is the thing to be returned,
 *  but he assumes that you'll have something correctly allocated to
 *  pass into this function.  Then he uses hbegin to go into the
 *  array, then he uses h to go to some place beyond hbegin, then he
 *  uses hh to do something else and then assigns a value to *hh.
 *  ahhhh!!!!1 
 *
 *  We need to make things a bit more clear so hopefully Boost can
 *  figure out what to do with all these arguments.  I'm thinking that
 *  once it's a bit more clear (like using array indices instead of
 *  pointer arithmetic) then we can trust Boost or even write a thing
 *  that takes python sequences as arguments and just let Boost do the
 *  other setup.  I don't yet know much about Boost, so i'll have to
 *  do some reading to see if it's worthwhile
 */


/*  
 * from the python wiki:
 * http://wiki.python.org/moin/boost.python/GettingStarted
 *
 * Relationship to the Python C API
 *
 * Python already provides an API for glueing together Python and
 * C. So what is Boost::Python? Boost::Python is a wrapper for the
 * Python/C API. 
 *
 * Using the Python/C API, you have to deal with passing pointers back
 * and forth between Python and C, and worry about pointers hanging
 * out in one place when the object they point to has been thrown
 * away. Boost::Python takes care of much of this for you. In
 * addition, Boost::Python lets you write operations on Python objects
 * in C++ in OOP style. 
 *
 * For example, using the Python/C API, to do the C++ equivalent of "y
 * = object_x[i]", you might do: 
 *
 * y = PySequence_GetItem(PyObject *object_x, int i);
 *
 * By contrast, in Boost::Python, you can just do:
 *
 * y = object_x[i];
 *
 * In addition, Boost::Python makes it easy to EXPORT your C++ classes
 * into Python, without even changing them. Boost::Python is designed
 * with the idea in mind that users never touch a PyObject*.  
 */


void straight_hough_array_f(
    float *arr, 
    int xsize, int xstart, int xend, int ystart, int yend,
    float *hough, 
    int rsize, int rstart, int rend, int tstart, int tend,
    float xbegin, float ybegin, float xincr, float yincr, float tbin)

/* The first pixel processed is at xbegin, ybegin in user coords */
{
  float   *arrslow, *arrfast, *arrslowend, *arrfastend,
    *h, *hbegin, *hend, *hh;
  int     xn = xend - xstart,
    thalf = rsize * (tend - tstart + 1);
  float   a, x, y, r,
    c, s, chold,
    cincr = cos(tbin), sincr = sin(tbin);
  int     rint;

  hbegin = hough + rsize * tstart + rstart;
  hend = hough + rsize * tend + rstart;

  for (arrslow = arr + xsize * ystart + xstart,
         arrslowend = arr + xsize * yend + xstart,
         y = ybegin;
       arrslow <= arrslowend;
       arrslow += xsize, y += yincr) {
    for (arrfast = arrslow,
	   arrfastend = arrslow + xn,
	   x = xbegin;
	 arrfast <= arrfastend;
	 arrfast++, x += xincr) {
      if ((a = *arrfast) != 0.0) {
	for (h = hbegin,
	       c = 1,   s = 0;   /* First bin is at angle zero */
	     h <= hend;
	     chold = c * cincr - s * sincr,
	       s = s * cincr + c * sincr,
	       c = chold,
	       h += rsize) {
	  r = x * c + y * s;
	  if (r < 0.0) {
	    rint = -r;  /* truncate */
	    hh = h + thalf + rint; }
	  else {
	    rint = r;   /* truncate */
	    hh = h + rint; 
	  }
	  *hh += a;
	}
      }
    }
  }
}

